# tell/persist.py
#
#

"""

    W E L C O M E  T O  T E L L !!!

    -=-

    (this code is best enjoyed on a wide screen)

"""

## tell imports

from tell import O, __version__
from .templates import headertxt

## basic import

import logging
import fcntl
import errno
import time
import json
import os

class Persist(O):

    ## Persist functionality - reading from and saving to disk

    def from_file(self, filename):
        input = self.load(j(self.root, filename))
        self.update(input)        

    def read(self, *args, **kwargs):
        """ read the JSON from file, skipping comments (lines starting with #). """
        try: f = open(self.get_path(), "r")
        except IOError as ex:
            if ex.errno == errno.ENOENT: return "{}"
            raise
        res = ""
        for line in f.readlines():
            if not line.strip().startswith("#"): res += line
        if not res.strip(): return "{}"
        f.close()
        return res

    def load(self, filename, verify=False, *args, **kwargs):
        """ convert the data on disk (a JSON dict) to this object. """
        self.filename = filename
        ondisk = self.read()
        self.prepare()
        fromdisk = O(**json.loads(ondisk))
        if "data" in fromdisk: result = O(**fromdisk.data)
        else: result = O(**fromdisk)
        if verify and fromdisk.signature:
            if self.make_signature(result) != fromdisk.signature: raise SignatureError(self.filename)
        self.update(result)
        return self

    def save_as(self, otype):
        self.otype = otype
        self.save()

    def save(self, *args, **kwargs):
        """ save current data to disk, using a container to hold meta data (signature etc.). """
        path = self.get_path()
        if not path: raise NoFileName()
        todisk = O(**self)
        todisk.wtime = time.time()
        todisk.signature = self.make_signature()
        try: result = todisk.full(indent=True)
        except TypeError: raise NoJSON(self.filename)
        datafile = open(path + ".tmp", 'w')
        fcntl.flock(datafile, fcntl.LOCK_EX | fcntl.LOCK_NB)
        datafile.write(headertxt % (__version__, self.filename, todisk.id(), time.ctime(todisk.wtime)))
        datafile.write(result)
        datafile.write("\n")
        fcntl.flock(datafile, fcntl.LOCK_UN)
        datafile.close()
        os.rename(path + ".tmp", path)
        logging.warn("save.%s" % self.filename)

    def get_fn(self, type, want="", ctimeplus=0, ctimemin=0, *args, **kwargs):
        target = get_kernel().root
        type_target = j(target, type)
        if os.path.isdir(type_target): target = type_target
        for fn in os.listdir(target):
            fn = j(self.root, fn)
            if not fn: continue
            splitted = fn.split(".")
            if splitted[0] != type: continue
            for item in splitted[1:]:
                if want and want not in f: continue
                try: ctime = float(item)
                except ValueError: yield(fn)
                if ctimeplus and ctime < ctimeplus : continue
                if ctimemin and ctime < ctimemin : continue
                yield(fn)

    def get_objects(self, type, *args, **kwargs):
        for fn in self.get_fn(*args, **kwargs): yield(O(filename=fn))



#### C O M M E N T  -=-  S E C T I O N

""" please write comments on changes you made below, so we can get log of things added/changed. """

## BHJTW 27-11-2012 initial import 
